#ifndef __MFRC522_DRIVER_H__
#define	__MFRC522_DRIVER_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../nfc_spi_driver.h"

//RST引脚
#define MFRC522_RST_GPIO_PORT      PortA
#define MFRC522_RST_GPIO_PIN       Pin2

//IRQ引脚(默认不用)


/* MFRC522命令字 */
#define MFRC522_PCD_IDLE           0x00    // 取消当前命令
#define MFRC522_PCD_MEM            0x01    // 存储命令（将数据从FIFO写入内部存储器）
#define MFRC522_PCD_GEN_RANDOM_ID  0x02    // 生成随机ID
#define MFRC522_PCD_CALCCRC        0x03    // CRC计算
#define MFRC522_PCD_TRANSMIT       0x04    // 发送FIFO数据
#define MFRC522_PCD_NO_CMD_CHANGE  0x07    // 无命令改变（用于获取当前状态）
#define MFRC522_PCD_AUTHENT        0x0E    // 验证密钥
#define MFRC522_PCD_RECEIVE        0x08    // 激活接收器接收数据
#define MFRC522_PCD_TRANSCEIVE     0x0C    // 发送并接收数据
#define MFRC522_PCD_MF_AUTHENT     0x0E    // MIFARE认证
#define MFRC522_PCD_RESETPHASE     0x0F    // 软复位

/*Mifare_One卡片命令字*/
#define MFRC522_PICC_TAG_TYPE_A    0x04    // MIFARE Classic Tag Type A
#define MFRC522_PICC_TAG_TYPE_B    0x05    // MIFARE Classic Tag Type B
#define MFRC522_PICC_REQIDL        0x26    // 寻天线区内未进入休眠状态
#define MFRC522_PICC_REQALL        0x52    // 寻天线区内全部卡
#define MFRC522_PICC_ANTICOLL1     0x93    // 防冲撞 级联标签1的选择命令
#define MFRC522_PICC_ANTICOLL2     0x95    // 防冲撞 级联标签2的选择命令
#define MFRC522_PICC_ANTICOLL3     0x97    // 防冲撞 级联标签3的选择命令
#define MFRC522_PICC_AUTHENT1A     0x60    // 验证A密钥
#define MFRC522_PICC_AUTHENT1B     0x61    // 验证B密钥
#define MFRC522_PICC_READ          0x30    // 读块
#define MFRC522_PICC_WRITE         0xA0    // 写块
#define MFRC522_PICC_DECREMENT     0xC0    // 扣款
#define MFRC522_PICC_INCREMENT     0xC1    // 充值
#define MFRC522_PICC_RESTORE       0xC2    // 调块数据到缓冲区
#define MFRC522_PICC_TRANSFER      0xB0    // 保存缓冲区中数据
#define MFRC522_PICC_HALT          0x50    // 休眠

/*MFRC522 FIFO长度定义*/
#define MFRC522_FIFO_LENGTH        64      // FIFO size=64byte
#define MFRC522_MAXRLEN            18

/*MF522寄存器定义*/
// PAGE 0 - 命令和状态寄存器
#define MFRC522_RFU00              0x00    // 保留未使用
#define MFRC522_CommandReg         0x01    // 控制MFRC522执行各种命令
#define MFRC522_ComIEnReg          0x02    // 通信中断使能寄存器
#define MFRC522_DivlEnReg          0x03    // 分频中断使能寄存器
#define MFRC522_ComIrqReg          0x04    // 通信中断标志寄存器
#define MFRC522_DivIrqReg          0x05    // 分频中断标志寄存器
#define MFRC522_ErrorReg           0x06    // 错误标志寄存器，显示执行命令后发生的错误
#define MFRC522_Status1Reg         0x07    // 状态寄存器1，显示通信状态
#define MFRC522_Status2Reg         0x08    // 状态寄存器2，显示接收器和发送器状态
#define MFRC522_FIFODataReg        0x09    // FIFO数据寄存器，用于读写FIFO缓冲区
#define MFRC522_FIFOLevelReg       0x0A    // FIFO级别寄存器，指示FIFO中字节数量
#define MFRC522_WaterLevelReg      0x0B    // FIFO水位寄存器，定义FIFO的触发深度
#define MFRC522_ControlReg         0x0C    // 控制寄存器，配置一般功能
#define MFRC522_BitFramingReg      0x0D    // 位帧寄存器，处理发送和接收的帧格式
#define MFRC522_CollReg            0x0E    // 冲突寄存器，包含防冲突处理的信息
#define MFRC522_RFU0F              0x0F    // 保留未使用

// PAGE 1 - 通信和调制寄存器
#define MFRC522_RFU10              0x10    // 保留未使用
#define MFRC522_ModeReg            0x11    // 模式寄存器，配置数据传输和调制方式
#define MFRC522_TxModeReg          0x12    // 发送模式寄存器，配置发送器逻辑
#define MFRC522_RxModeReg          0x13    // 接收模式寄存器，配置接收器逻辑
#define MFRC522_TxControlReg       0x14    // 发送控制寄存器，控制天线驱动器
#define MFRC522_TxAutoReg          0x15    // 发送自动寄存器，控制调制
#define MFRC522_TxSelReg           0x16    // 发送选择寄存器，选择发送通道
#define MFRC522_RxSelReg           0x17    // 接收选择寄存器，选择接收通道
#define MFRC522_RxThresholdReg     0x18    // 接收阈值寄存器，设置接收器灵敏度
#define MFRC522_DemodReg           0x19    // 解调寄存器，配置解调器
#define MFRC522_RFU1A              0x1A    // 保留未使用
#define MFRC522_RFU1B              0x1B    // 保留未使用
#define MFRC522_MifareReg          0x1C    // Mifare经典协议特定配置
#define MFRC522_RFU1D              0x1D    // 保留未使用
#define MFRC522_RFU1E              0x1E    // 保留未使用
#define MFRC522_SerialSpeedReg     0x1F    // 串行速度寄存器，配置串行UART速度

// PAGE 2 - 定时器和CRC寄存器
#define MFRC522_RFU20              0x20    // 保留未使用
#define MFRC522_CRCResultRegM      0x21    // CRC结果寄存器高字节
#define MFRC522_CRCResultRegL      0x22    // CRC结果寄存器低字节
#define MFRC522_RFU23              0x23    // 保留未使用
#define MFRC522_ModWidthReg        0x24    // 调制宽度寄存器，定义调制宽度
#define MFRC522_RFU25              0x25    // 保留未使用
#define MFRC522_RFCfgReg           0x26    // RF配置寄存器，配置RF放大器
#define MFRC522_GsNReg             0x27    // 增益选择寄存器，设置接收增益
#define MFRC522_CWGsCfgReg         0x28    // 连续波增益配置寄存器
#define MFRC522_ModGsCfgReg        0x29    // 调制增益配置寄存器
#define MFRC522_TModeReg           0x2A    // 定时器模式寄存器，配置定时器
#define MFRC522_TPrescalerReg      0x2B    // 定时器预分频器寄存器
#define MFRC522_TReloadRegH        0x2C    // 定时器重载值高字节
#define MFRC522_TReloadRegL        0x2D    // 定时器重载值低字节
#define MFRC522_TCounterValueRegH  0x2E    // 定时器当前值高字节
#define MFRC522_TCounterValueRegL  0x2F    // 定时器当前值低字节

// PAGE 3 - 测试和版本寄存器
#define MFRC522_RFU30              0x30    // 保留未使用
#define MFRC522_TestSel1Reg        0x31    // 测试选择1寄存器，用于芯片测试
#define MFRC522_TestSel2Reg        0x32    // 测试选择2寄存器，用于芯片测试
#define MFRC522_TestPinEnReg       0x33    // 测试引脚使能寄存器
#define MFRC522_TestPinValueReg    0x34    // 测试引脚值寄存器
#define MFRC522_TestBusReg         0x35    // 测试总线寄存器
#define MFRC522_AutoTestReg        0x36    // 自动测试寄存器
#define MFRC522_VersionReg         0x37    // 版本寄存器，显示芯片版本
#define MFRC522_AnalogTestReg      0x38    // 模拟测试寄存器
#define MFRC522_TestDAC1Reg        0x39    // 测试DAC1寄存器
#define MFRC522_TestDAC2Reg        0x3A    // 测试DAC2寄存器
#define MFRC522_TestADCReg         0x3B    // 测试ADC寄存器
#define MFRC522_RFU3C              0x3C    // 保留未使用
#define MFRC522_RFU3D              0x3D    // 保留未使用
#define MFRC522_RFU3E              0x3E    // 保留未使用
#define MFRC522_RFU3F              0x3F    // 保留未使用

/*MFRC522错误代码*/
#define MI_OK                      0       // 操作成功
#define MI_NOTAGERR                1       // 没有卡片错误
#define MI_ERR                     2       // 其他错误
#define MI_COLLISION               3       // 防冲突错误（多张卡冲突）
#define MI_TIMEOUT                 4       // 超时错误
#define MI_AUTH_ERROR              5       // 认证失败
#define MI_WRITE_ERROR             6       // 写入失败
#define MI_READ_ERROR              7       // 读取失败
#define MI_ACK                     0xA     // 卡片确认应答（ACK）

/* 卡片类型枚举 */
typedef enum
{
    PICC_TYPE_UNKNOWN          = 0x00,  // 未知类型
    PICC_TYPE_ISO14443_4       = 0x01,  // 符合ISO/IEC 14443-4标准
    PICC_TYPE_ISO18092         = 0x02,  // 符合ISO/IEC 18092 (NFC)标准
    PICC_TYPE_MIFARE_MINI      = 0x03,  // MIFARE Mini (320字节)
    PICC_TYPE_MIFARE_1K        = 0x04,  // MIFARE 1K (1024字节)
    PICC_TYPE_MIFARE_4K        = 0x05,  // MIFARE 4K (4096字节)
    PICC_TYPE_MIFARE_UL        = 0x06,  // MIFARE Ultralight/Ultralight C
    PICC_TYPE_MIFARE_PLUS      = 0x07,  // MIFARE Plus
    PICC_TYPE_MIFARE_DESFIRE   = 0x08,  // MIFARE DESFire
    PICC_TYPE_TNP3XXX          = 0x09,  // TNP3XXX系列
    PICC_TYPE_NOT_COMPLETE     = 0xFF   // UID不完整
}PICC_Type;

/* 卡片类型码ATQA/SAK值 */
typedef enum
{
    MIFARE_Classic_1K    = 0x000408,
    MIFARE_Classic_4K    = 0x000218,
    MIFARE_Ultralight    = 0x004400,
    MIFARE_Mini	         = 0x000409,
    MIFARE_Plus_SL1	     = 0x000210,
    MIFARE_Plus_SL2	     = 0x000211,
    MIFARE_DESFire	     = 0x004420,
    ISO14443_4_compliant = 0x034420,
}PICC_Type_Code;


/* M1卡访问权限 */
typedef enum
{
    /* C1 C2 C3 MSB格式 */
    Data_Block_R_AB_W_AB__I_AB__DTR_AB     = 0,//读:keyA/B 写:KeyA/B 加值:keyA/B 减值转移值恢复值:KeyA/B
    Data_Block_R_AB_W_Not__I_Not__DTR_AB   = 1,//读:keyA/B 写:Never  加值:Never  减值转移值恢复值:KeyA/B
    Data_Block_R_AB_W_Not__I_Not__DTR_Not  = 2,//读:keyA/B 写:Never  加值:Never  减值转移值恢复值:Never
    Data_Block_R_B_W_B__I_Not__DTR_Not     = 3,//读:keyB   写:KeyB   加值:Never  减值转移值恢复值:Never
    Data_Block_R_AB_W_B__I_Not__DTR_Not    = 4,//读:keyA/B 写:KeyB   加值:Never  减值转移值恢复值:Never
    Data_Block_R_B_W_Not__I_Not__DTR_Not   = 5,//读:keyB   写:Never  加值:Never  减值转移值恢复值:Never
    Data_Block_R_AB_W_B__I_B__DTR_AB       = 6,//读:keyA/B 写:KeyB   加值:keyB   减值转移值恢复值:KeyA/B
    Data_Block_R_Not_W_Not__I_Not__DTR_Not = 7,//读:Never  写:Never  加值:Never  减值转移值恢复值:Never

    Ctrl_Block_R_Not_W_AB__R_AB_W_Not__R_AB_W_AB    = 0,//密钥A:读Newer 写keyA/B 控制字:读KeyA/B 写Never 密钥B:读KeyA/B 写keyA/B
    Ctrl_Block_R_Not_W_AB__R_AB_W_AB__R_AB_W_AB     = 1,//密钥A:读Newer 写keyA/B 控制字:读KeyA/B 写keyA/B密钥B:读keyA/B 写keyA/B
    Ctrl_Block_R_Not_W_Not__R_AB_W_Not__R_AB_W_Not  = 2,//密钥A:读Newer 写Newer  控制字:读KeyA/B 写Never 密钥B:读KeyA/B 写Newer
    Ctrl_Block_R_Not_W_B__R_AB_W_B__R_Not_W_B       = 3,//密钥A:读Newer 写keyB   控制字:读KeyA/B 写keyB  密钥B:读Newer  写keyB
    Ctrl_Block_R_Not_W_B__R_AB_W_Not__R_Not_W_B     = 4,//密钥A:读Newer 写keyB   控制字:读KeyA/B 写Never 密钥B:读Newer  写KeyB
    Ctrl_Block_R_Not_W_Not__R_AB_W_B__R_Not_W_Not   = 5,//密钥A:读Newer 写Newer  控制字:读KeyA/B 写keyB  密钥B:读Newer  写Newer
    Ctrl_Block_R_Not_W_Not__R_AB_W_Not__R_Not_W_Not = 6,//密钥A:读Newer 写Newer  控制字:读KeyA/B 写Never 密钥B:读Newer  写Newer
    Ctrl_Block_R_Not_W_Not__R_AB_W_Not__R_Not_W_Not_= 7,//密钥A:读Newer 写Newer  控制字:读KeyA/B 写Newer 密钥B:读Newer  写Newer
}Mifare_One_Access_Rights_enum;

typedef struct
{
    uint8_t Block_Data[3][16];//3个快，每块16字节
    uint8_t Password_A[6];    //密钥A
    uint8_t Ctrl_Word[4];     //控制字
    uint8_t Password_B[6];    //密钥B
}Mifare_One_Sector_t;

typedef struct
{
    uint8_t Block_Data[15][16];//15个快，每块16字节
    uint8_t Password_A[6];     //密钥A
    uint8_t Ctrl_Word[4];      //控制字
    uint8_t Password_B[6];     //密钥B
}Mifare_One_Sector_Plus_t;

typedef struct
{
    Mifare_One_Sector_t Sector[16];
    uint8_t UID[8];
}Mifare_S50_t;

typedef struct
{
    Mifare_One_Sector_t Sector[32];
    Mifare_One_Sector_Plus_t Sector_plus[8];
    uint8_t UID[8];
}Mifare_S70_t;






/* 复位 */
void MFRC522_Restart(void);
/* 设置工作方式 */
void MFRC522_Set_ISP_Type(uint8_t type);
/* 初始化 */
void MFRC522_Init(void);


/**
  * @brief 寻卡
  * @param  Req_code，0x52 寻感应区内所有符合14443A标准的卡；
            0x26 寻未进入休眠状态的卡
  * @param  TagType，卡片类型代码
  * @retval 状态值= MI_OK，成功
  */
uint8_t MFRC522_Request(uint8_t req_code, uint8_t* out_tag_type);

/* 防冲撞 获取卡UID*/
uint8_t MFRC522_Anticoll_Get_UID(uint8_t* out_uid);

/* 选定指定UID的卡 */
uint8_t MFRC522_Select_Tag_Card(uint8_t* in_uid);

/**
  * @brief  验证卡片密码
  * @param  Auth_mode，密码验证模式 0x60验证A密钥，0x61验证B密钥
  * @param  block_addr，块地址
  * @param  Key，密码 
  * @param  uid，卡片序列号，4字节
  * @retval 状态值= MI_OK，成功
  */
uint8_t MRC522_Tag_Card_Auth(uint8_t auth_mode, uint8_t block_addr, uint8_t* in_key, uint8_t* in_uid);

/* 写指定的块数据 */
uint8_t MFRC522_Write_Block(uint8_t block_addr, uint8_t in_data[16]);

/* 读指定的块数据 */
uint8_t MFRC522_Read_Block(uint8_t block_addr, uint8_t out_data[16]);

/* 判断是否数据块 */
uint8_t MFRC522_Is_Data_Block(uint8_t block_addr);

/* 标签卡休眠 */
uint8_t MFRC522_Tag_Card_Halt(void);


/**************************** 增强功能 ****************************/
/* 获取固件版本 */
uint8_t MFRC522_Get_Firmware_Version(void);
/* 检查是否有新卡出现 */
uint8_t MFRC522_Is_New_Card_Present(void);
/* 获取卡片类型 */
uint8_t MFRC522_Get_Card_Type(uint8_t* buffer);
/* 增值操作 */
uint8_t MFRC522_Increment(uint8_t block_addr, uint32_t value);
/* 减值操作 */
uint8_t MFRC522_Decrement(uint8_t block_addr, uint32_t value);
/* 恢复操作 - 将块中的值加载到内部数据寄存器 */
uint8_t MFRC522_Restore(uint8_t block_addr);
/* 传输操作 - 将内部数据寄存器的值存储到块中 */
uint8_t MFRC522_Transfer(uint8_t block_addr);
/* 软件断电 */
void MFRC522_Soft_Power_Down(void);
/* 软件上电 */
void MFRC522_Soft_Power_Up(void);
/* 更新控制字 */
void Mifare_One_Update_Ctrl_Word(uint8_t block_addr, Mifare_One_Access_Rights_enum access_rights, uint8_t src_ctrl_word[4], uint8_t dst_ctrl_word[4]);
/* 获取块的访问权限 */
Mifare_One_Access_Rights_enum Mifare_One_Get_Block_Rights(uint8_t block_addr, uint8_t src_ctrl_word[4]);
/* 修改密码A */
uint8_t MFRC522_Change_KeyA(uint8_t block_addr, uint8_t* in_uid, uint8_t in_KeyB[6], uint8_t new_KeyA[6]);
/* 修改密码B */
uint8_t MFRC522_Change_KeyB(uint8_t block_addr, uint8_t* in_uid, uint8_t in_KeyB[6], uint8_t new_KeyB[6]);
/* 打印MIFARE Classic 1K卡内容到串口 */
void MFRC522_Dump_Classic_1K_To_Serial(Mifare_S50_t* out_data, uint8_t *uid);
/* 打印MIFARE Classic 4K卡内容到串口 */
void MFRC522_Dump_Classic_4K_To_Serial(uint8_t *uid);

#endif /* __MFRC522_DRIVER_H__ */
